﻿#include"XQTimeChartsWidget.h"
#include"XQFuncEvent.h"
#include"XQTaskPool.h"
#include"XSymbolOverload.h"
#include"XQTimeDoubleDataModel.h"
#include"XQTimeSelectDockWidget.h"
#include"XQChartView_XYSeries.h"
#include<QXYSeries>
#include<QChartView>
#include<QLineSeries>
#include<QDateTimeAxis>
#include<QValueAxis>
XQTimeChartsWidget::XQTimeChartsWidget(QWidget* parent)
	:QWidget(parent)
{
	init();
}

XQTimeChartsWidget::XQTimeChartsWidget(const QString& title, QWidget* parent)
	:QWidget(parent)
{
	init();
	setWindowTitle(title);
}

XQTimeChartsWidget::~XQTimeChartsWidget()
{
	m_task->requestInterruption();
	m_task->wait();
}

XQTimeDoubleDataModel* XQTimeChartsWidget::model(const QString& sign) const
{
	if(m_model.find(sign)!=m_model.end())
		return m_model[sign];
	return nullptr;
}

XQTimeDoubleDataModel* XQTimeChartsWidget::model(int sign) const
{
	return model(QString::number(sign));
}

size_t XQTimeChartsWidget::modelSize() const
{
	return m_model.size();
}

size_t XQTimeChartsWidget::seriesSize() const
{
	return m_Series.size();
}

double XQTimeChartsWidget::getTimeChangePercent(const QString& sign, QDateTime* startOut, QDateTime* endOut)
{
	auto model = this->model(sign);
	auto type = m_selectWidget->selectTimeType();
	if(model==nullptr||model->datas().isEmpty()||type==TimeInterval::null)
		return 0.0;
	auto dates = model->datas().keys();//所有的日期
	QDateTime startDate;
	QDateTime endDate;
	if (type == TimeInterval::userDefined)
	{
		startDate = m_selectWidget->startDateTime();
		endDate = m_selectWidget->endDateTime();
	}
	else if (type == TimeInterval::hitherto)
	{
		startDate = dates.front();
		endDate = dates.back();
	}
	else
	{
		endDate = dates.back();//已有的最近时间
		startDate = m_selectWidget->selectDateTime(endDate);
	}
	auto value =model->changePercent(startDate, endDate, &startDate, &endDate);
	*startOut = startDate;
	*endOut = endDate;
	return value;
}

XQTimeSelectDockWidget* XQTimeChartsWidget::selectWidget() const
{
	return m_selectWidget;
}

QDateTimeAxis* XQTimeChartsWidget::AxisX() const
{
	return static_cast<QDateTimeAxis*>(m_chartView->chart()->axisX());
}

QValueAxis* XQTimeChartsWidget::AxisY() const
{
	return static_cast<QValueAxis*>(m_chartView->chart()->axisY());
}

QMainWindow* XQTimeChartsWidget::mainWindow() const
{
	return m_mainWindow;
}

XQStatusBarWidget* XQTimeChartsWidget::statusBar() const
{
	return m_statusbar;
}

void XQTimeChartsWidget::addModel(const QString& sign, XQTimeDoubleDataModel* model)
{
	if(!sign.isEmpty()&&model)
		m_model[sign] = model;
}

void XQTimeChartsWidget::addModel(int sign, XQTimeDoubleDataModel* model)
{
	addModel(QString::number(sign),model);
}

void XQTimeChartsWidget::removeModel(const QString& sign, bool Delete)
{
	if (model(sign))
	{
		if (Delete)
			model(sign)->deleteLater();
		m_model.remove(sign);
	}
}

void XQTimeChartsWidget::removeModel(int sign, bool Delete)
{
	removeModel(QString::number(sign), Delete);
}

void XQTimeChartsWidget::clearModel()
{
	m_model.clear();
}

void XQTimeChartsWidget::addCharts(const QString& sign, QXYSeries* series)
{
	auto model = this->model(sign);
	if (model == nullptr || series == nullptr)
		return;
	m_task->addTask([=] {
		emit showMessage("开始计算", 10_s);
		auto& datas = model->datas();//数据
		if (datas.isEmpty())//是空的
		{
			new XQFuncEvent(this, [=] {
				setEnabled(true); 
				series->deleteLater();
				clearSeries(sign); });
			emit showMessage("数据是空的", 10_s);
			return;
		}
		QDateTime startDate, endDate;

		//获取时间范围
		auto value = getTimeChangePercent(sign,&startDate, &endDate);
		auto chart = m_chartView->chart();
		//判断是否为空
		auto it = datas.find(startDate);
		if (it == datas.end()|| startDate.isNull()|| endDate.isNull())
		{//是空的
			emit showMessage("数据是空的", 10_s);
			return;
		}
		//添加数据
		auto itEnd = ++datas.find(endDate);
		for (; it != itEnd; it++)
		{
			double x = it.key().toMSecsSinceEpoch();
			double y = it.value();
			*series << QPointF(x, y);
		}
		new XQFuncEvent(this, [=] {newSeries_setting(sign,series,startDate,endDate);
		emit showMessage("显示完成", 3_s);
			});
		});
}
void XQTimeChartsWidget::addCharts(int sign, QXYSeries* series)
{
	addCharts(QString::number(sign), series);
}
void XQTimeChartsWidget::removeCharts(const QString& sign)
{
	if (m_Series[sign])
	{
		clearSeries(sign);
	}
}
void XQTimeChartsWidget::removeCharts(int sign)
{
	removeCharts(QString::number(sign));
}
void XQTimeChartsWidget::selectChartsTime()
{
	for (auto&sign: m_model.keys())
	{
		auto series = new QLineSeries(this);
		if(m_Series[sign])
		{
			series->setName(m_Series[sign]->name());//继承名字
			series->setObjectName(m_Series[sign]->objectName());
		}
		addCharts(sign, series);
	}
}
void XQTimeChartsWidget::wait()
{
	m_task->wait_event();
}
void XQTimeChartsWidget::clearSeries(const QString& sign)
{
	if (m_Series[sign])
	{
		if (m_chartView->selectSeries() == m_Series[sign])
			m_chartView->setSelectSeries(nullptr);
		auto chart = this->m_chartView->chart();
		chart->removeSeries(m_Series[sign]);
		m_Series[sign]->deleteLater();
		m_Series.remove(sign);
	}
}
void XQTimeChartsWidget::newSeries_setting(const QString& sign, QXYSeries* series, const QDateTime& startDate, const QDateTime& endDate)
{
	auto chart = this->m_chartView->chart();
	//清除上一次的添加
	clearSeries(sign);
	m_Series[sign] = series;//加入容器记录下来
	chart->addSeries(series);
	series->setPointLabelsClipping(false);//标签不裁剪
	//auto chart = m_chartView->chart();
	//坐标轴重新设置范围
	AxisRange_setting(startDate, endDate);


	chart->hide();
	chart->show();
	setEnabled(true);
}
void XQTimeChartsWidget::AxisRange_setting(const QDateTime& startDate, const QDateTime& endDate)
{
	auto chart = m_chartView->chart();
	auto AxisX = chart->axisX();
	auto AxisY = chart->axisY();
	chart->removeAxis(AxisX);
	chart->addAxis(AxisX, Qt::AlignBottom);
	chart->removeAxis(AxisY);
	chart->addAxis(AxisY, Qt::AlignLeft);
	//计算坐标轴范围
	qreal XMinsec = INT_FAST64_MAX, XMaxsec = -INT_FAST64_MAX;
	qreal YMinsec = INT_FAST64_MAX, YMaxsec = -INT_FAST64_MAX;
	for (auto& data : m_model)
	{
		auto ret = data->value_min_max(startDate, endDate);
		YMinsec = qMin(YMinsec, ret.first);
		YMaxsec = qMax(YMaxsec, ret.second);
	}
	AxisX->setRange(startDate, endDate);
	AxisY->setRange(YMinsec, YMaxsec);
	//将坐标轴设置回去
	for (auto& series : m_Series)
	{
		series->attachAxis(AxisX); series->attachAxis(AxisY);
	}
}

QString XQTimeChartsWidget::ShowDataToolTip(QXYSeries* series, const QPointF& pointf)
{
	/*	auto sign=m_Series.key(series);
		auto model = m_model[sign];*/
	QString text;
	auto name = series->name();
	if (!name.isEmpty())
		text += (name + "\r\n");
	auto startValue = series->at(0).y();
	text+= QString("数值:%1\r\n日期:%2\r\n涨跌值:%3%")
		.arg(QString::number(pointf.y(), 'f', 2))
		.arg(QDateTime::fromMSecsSinceEpoch(pointf.x()).toString("yyyy-MM-dd"))
		.arg(QString::number((pointf.y() / startValue - 1) * 100, 'f', 2));
	return std::move(text);
}
